import numpy as np
import xlrd


def load_hour_data(filepath):
    data = xlrd.open_workbook(filepath)
    arrive_sheet = data.sheet_by_index(0)
    rows, cols = arrive_sheet.nrows, arrive_sheet.ncols
    every_rows = np.empty((rows, cols))
    for row in range(rows):
        for col in range(cols):
            every_rows[row][col] = arrive_sheet.cell_value(row, col)
    hour_border = np.array(np.linspace(59, rows, 72))
    everyhour = np.zeros((72, 2))
    col1_value, col2_value = 0, 0

    for minute in range(int(hour_border[0])):
        everyhour[0][0] += every_rows[minute][0]
        everyhour[0][1] += every_rows[minute][1]
    for row in range(1, 72):
        for minute in range(int(hour_border[row - 1]), int(hour_border[row])):
            col1_value += every_rows[minute][0]
            col2_value += every_rows[minute][1]
        everyhour[row][0] = col1_value
        everyhour[row][1] = col2_value
        col1_value = 0
        col2_value = 0

    deadline = np.array([14, 4, 6])
    deadline = np.tile(deadline, 3)
    for i in range(1, len(deadline)):
        deadline[i] += deadline[i - 1]
    return everyhour, deadline


class TransferStation:
    def __init__(self, equipment1num, equipment2num, initordinarynum):
        self.__complete_flag = True
        self.__equipment1_ability = 400
        self.__equipment2_ability = 500
        self.__equipment1_num = equipment1num
        self.__equipment2_num = equipment2num
        self.__ordinary_express = initordinarynum
        self.__postpone_express = 0
        self.__emergency_express = 0
        self.__record1_num = self.__equipment1_num
        self.__record2_num = self.__equipment2_num

    def get_express_num(self):
        return self.__ordinary_express, self.__emergency_express, self.__postpone_express

    def get_equipment_num(self):
        return self.__equipment1_num, self.__equipment2_num

    def set_equipment_num(self):
        pass

    def set_express_num(self):
        pass

    def add_new_equipment(self, add1_num, add2_num):
        self.__equipment1_num += add1_num
        self.__equipment2_num += add2_num
        return

    def grasp_express(self, grasp_express_num):
        self.__emergency_express += int(grasp_express_num[1])
        self.__ordinary_express += int(grasp_express_num[0]) - int(grasp_express_num[1])
        return

    def handle_express(self):
        handle_ability = self.__equipment1_ability * self.__equipment1_num \
                         + self.__equipment2_num * self.__equipment2_ability
        # print("\ncurrent handle ability:", handle_ability, "\n")
        if handle_ability >= self.__emergency_express:
            self.__complete_flag = True
            handle_ability -= self.__emergency_express
            self.__emergency_express = 0
            if handle_ability >= self.__postpone_express:
                handle_ability -= self.__postpone_express
                self.__postpone_express = 0
                self.__ordinary_express = max(0, self.__ordinary_express - handle_ability)
            else:
                self.__postpone_express -= handle_ability
        else:
            self.__complete_flag = False
            # print("Error Code 1: Unable to complete current task!\n")
        return

    def adjust_phase(self):
        self.__postpone_express = self.__ordinary_express
        self.__ordinary_express = 0
        return

    def deadline_judgment(self):
        if self.__postpone_express > 0:
            self.__complete_flag = False
            # print("Error Code 2: Unable to complete current task!\n")
        else:
            self.__complete_flag = True

    def get_complete_flag(self):
        return self.__complete_flag

    def sleep(self, sleep_signal, sleep1_num, sleep2_num):
        self.__record1_num = self.__equipment1_num
        self.__record2_num = self.__equipment2_num
        # print("I'm going to sleep!")
        if sleep_signal == 1:
            self.__equipment1_num = self.__equipment1_num - sleep1_num
        elif sleep_signal == 2:
            self.__equipment2_num = self.__equipment2_num - sleep2_num
        elif sleep_signal == 3:
            self.__equipment1_num = self.__equipment1_num - sleep1_num
            self.__equipment2_num = self.__equipment2_num - sleep2_num

    def restart(self):
        self.__equipment1_num = self.__record1_num
        self.__equipment2_num = self.__record2_num


if __name__ == '__main__':
    file_path = 'data.xlsx'
    init_equipment1_num = 12
    init_equipment2_num = 0
    every_hour, deadline_border = load_hour_data(file_path)
    phase_border = deadline_border - 2
    # print(every_hour, deadline_border, phase_border)
    sleep_hour = 1
    init_ordinary_num = int(every_hour[-2][0] - every_hour[-2][1]
                            + every_hour[-1][0] - every_hour[-1][1])

    # 仅使用设备1处理问题
    print("********Use only device 1 to handle problem 2********")
    for add_equip1 in range(10):
        add_equip2 = 0
        transfer = TransferStation(init_equipment1_num, init_equipment2_num, init_ordinary_num)
        transfer.add_new_equipment(add_equip1, add_equip2)
        equipment1_num, equipment2_num = transfer.get_equipment_num()
        phase = 0
        for hour in range(72):
            transfer.grasp_express(every_hour[hour])
            # num1, num2, num3 = transfer.get_express_num()
            # print("********Before deal********")
            # print("ordinary num:", num1, "\nemergency num:", num2, "\npostpone num:", num3)
            if (hour + 1) % 9 == sleep_hour:
                transfer.sleep(1, equipment1_num - 1, 0)
            elif (hour + 1) % 9 == sleep_hour + 1:
                transfer.sleep(1, 1, 0)
            transfer.handle_express()
            if not transfer.get_complete_flag():
                print("Error-number of current devices 1:", equipment1_num)
                print("Error-number of current devices 2:", equipment2_num)
                break
            if hour == phase_border[phase] - 1:
                transfer.adjust_phase()
            if hour == deadline_border[phase] - 1:
                # print(hour)
                phase += 1
                transfer.deadline_judgment()
                if not transfer.get_complete_flag():
                    print("Error-number of current devices 1:", equipment1_num)
                    print("Error-number of current devices 2:", equipment2_num)
                    break
            transfer.restart()
            # print(transfer.get_complete_flag())
            # num1, num2, num3 = transfer.get_express_num()
            # print("********After deal********")
            # print("ordinary num:", num1, "\nemergency num:", num2, "\npostpone num:", num3)
        if transfer.get_complete_flag():
            print("Number of current devices 1:", equipment1_num,)
            print("Number of current devices 2:", equipment2_num,)
            break
        del transfer

    print("\n\n")
    # 仅使用设备2处理问题
    print("********Use devices 1 and 2 to handle problem 2********")
    for add_equip2 in range(10):
        add_equip1 = 0
        transfer2 = TransferStation(init_equipment1_num, init_equipment2_num, init_ordinary_num)
        transfer2.add_new_equipment(add_equip1, add_equip2)
        equipment1_num, equipment2_num = transfer2.get_equipment_num()
        phase = 0
        for hour in range(72):
            transfer2.grasp_express(every_hour[hour])
            if (hour + 1) % 9 == sleep_hour and (hour + 1) % 13 == sleep_hour:
                transfer2.sleep(3, equipment1_num - 1, equipment2_num)
            elif (hour + 1) % 9 == sleep_hour:
                transfer2.sleep(1, equipment1_num - 1, 0)
            elif (hour + 1) % 13 == sleep_hour:
                transfer2.sleep(2, 0, equipment2_num)
            elif (hour + 1) % 9 == sleep_hour + 1:
                transfer2.sleep(1, 1, 0)
            transfer2.handle_express()
            if not transfer2.get_complete_flag():
                print("Error-number of current devices 1:", equipment1_num)
                print("Error-number of current devices 2:", equipment2_num)
                break
            if hour == phase_border[phase] - 1:
                transfer2.adjust_phase()
            if hour == deadline_border[phase] - 1:
                phase += 1
                transfer2.deadline_judgment()
                if not transfer2.get_complete_flag():
                    print("Error-number of current devices 1:", equipment1_num)
                    print("Error-number of current devices 2:", equipment2_num)
                    break
            transfer2.restart()
        if transfer2.get_complete_flag():
            print("Number of current devices 1:", equipment1_num)
            print("Number of current devices 2:", equipment2_num)
            break
        del transfer2

